/**
 * @brief 3.5.1 定义和初始化内置数组
 * 数组是一种复合类型
 * 数组中元素的个数也属于数组类型的一部分，编译的时候维度应该是已知的。也就是说，维度必须是一个常量表达式
 */
#include <iostream>
#include <string>
using std::cin, std::cout, std::endl;
using std::string;

constexpr int get_size();
constexpr int get_size()
{
    return 1 + 1;
}
int arr1[10];

int main(int argc, char const *argv[])
{
    // 数组的维度必须是一个常量表达式
    unsigned cnt = 42;
    constexpr unsigned sz = 42;
    int arr[10];             // 正确
    int *parr[sz];           // 正确
    string bad[cnt];         // 错误，cnt不是常量表达式
    string strs[get_size()]; // 当get_size是constexpr时正确，否则错误

    // 和内置类型的变量一样，如果在函数内部定义了某种内置类型的数组，那么默认初始化会令数组含有未定义的值。
    for (auto c : arr) // arr定义在函数体内，值是未定义的
    {
        cout << c << " "; // 例如：1867014224 593 16 0 0 0 -703719320 32758 -703720160 32758
    }
    cout << endl;
    for (auto c : arr1) // arr1定义在函数体外，值被默认初始化为0
    {
        cout << c << " ";
    }
    cout << endl;

    // 显示初始化数组元素
    const unsigned sz1 = 3;
    int ia1[sz1] = {0, 1, 2};
    int ia2[] = {0, 1, 2};
    int ia3[5] = {0, 1, 2};        // 等价于ia3[] = {0,1,2,0,0}
    string ia4[3] = {"hi", "bye"}; // 等价于ia3[] = {"hi","bye",""}
    //int ia5[2] = {0, 1, 2};        // 错误，初始化值过多

    // 字符数组的特殊性
    // 一定要注意字符串字面值的结尾处还有一个空字符，这个空字符也会像字符串的其他字符一样被拷贝到字符数组中去
    char ch1[] = {'C','+','+'}; // 列表初始化，没有空字符
    char ch2[] = {'C','+','+','\0'}; // 列表初始化，有显示的空字符
    char ch3[] = "C++"; // 自动添加表示字符串结束的空字符，字符数组ch3的长度为4
    //const char ch[4] = "abcd"; // 错误，没有空间可以存放空字符

    // 不允许拷贝和赋值
    // 不能将数组的内容拷贝给其他数组作为其初始值，也不能用数组为其他数组赋值
    int a[] = {0,1,2};
    //int a1[] = a; // 错误，不允许使用一个数组初始化另一个数组
    //a1 = a; // 错误，不能把一个数组赋值给另一个数组

    // 理解复杂的数组声明
    // 因为数组本身就是对象，所以允许定义数组的指针及数组的引用。
    // 定义存放指针的数组比较简单和直接，但是定义数组的指针或数组的引用就稍微复杂一点了
    int *ptrs[10]; // ptrs是含有10个整型指针的数组
    //int &refs[10] = /* ? */; // 错误，不存在引用的数组
    int (*Parray)[10] = &arr; // Parray是数组的指针，指向一个含有10个整数的数组
    int (&arrRef)[10] = arr; // arrRef是数组的引用，引用一个含有10个整数的数组
    // 数组的定义，应由内向外读，例如：Parray是一个指针，它指向一个int数组，数组中包含10个元素。
    int *(&array)[10] = ptrs; // array是数组的引用，该数组含有10个整型指针

    return 0;
}
